#ifndef _TALK_SESSION_STR_STRCORE_H_
#define _TALK_SESSION_STR_STRCORE_H_

#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/client/httpportallocator.h"
#include "talk/p2p/client/sessionmanagertask.h"

#include "talk/examples/crossfirewall/cflogin.h"
#include "talk/examples/crossfirewall/cfcallmanager.h"
#include "talk/examples/crossfirewall/cfsessionclient.h"



#define  CMD_CORE_RELOGIN		0

enum Login_State{
	LOGIN_STATE_LOGOUT = 0,
	LOGIN_STATE_LOGINING,
	LOGIN_STATE_LOGINED
};

struct status_msg{
	int version;
	int status;
	int error;
	char reason[120];
};

typedef void (*lscb)(const struct status_msg);
typedef void (*rscb)(const char* jid, int sid, const char* pc, const char* status);
typedef void (*cscb)(const char* jid, int state);


class CFCore : public sigslot::has_slots<> 
{
public:
	CFCore();
	~CFCore();

	bool Login(const char* usrname, const char* usrpass, const char * computername, const char * resource);
	bool Logout();
	void ReLogin();

	void MakeCall(const char* remote_jid);
	void MakeCall_w(const char* remote_jid);

	void HangupCall(const char* remote_jid);
	void HangupCall_w(const char* remote_jid);

	void DestroyCall(const char* remote_jid);
	void DestroyCall_w(const char* remote_jid);

	void HangupCallAll();
	void HangupCallAll_w();

	void SetCoreCallBack(lscb ls_cb, rscb rs_cb, cscb cs_cb) { ls_cb_ = ls_cb;  rs_cb_ = rs_cb;  cs_cb_ = cs_cb; }

public:
	void OnInitCore();
	void OnUnInitCore();

	void OnLoginRosterChange(const cricket::RosterItem& item);
	void OnLoginStateChange(const cricket::LoginState& state);
	void OnCallStateChange(const cricket::CallState& state);

	void OnLoginBombTimeout() { cf_login_.BombLoginBomb(); }
	void OnLoginDoPing() { cf_login_.Ping(); }
	void OnXmppFlush() { cf_login_.OnFlushXmpp(); }
	void OnLoginJingleInfo(const std::string & relay_token, const std::vector<std::string> &relay_addresses,
		const std::vector<talk_base::SocketAddress> &stun_addresses) {
			cfcall_mannager_->SetHttpAllocatorHosts(relay_token, relay_addresses, stun_addresses);
	}


private:
	void SetLoginStatus(int state) { talk_base::CritScope cs(&core_crit_);  login_state_ = state; }

private:
	int login_state_;
	talk_base::CriticalSection    core_crit_;
	
	talk_base::Thread*            cmd_thread_;
	cricket::CmdConsole*          cmd_console_;
	talk_base::ThreadManager*     thread_manager_;

	cricket::CFLogin              cf_login_;
	cricket::CFCallManager*       cfcall_mannager_;

	lscb ls_cb_;
	rscb rs_cb_;
	cscb cs_cb_;
};

#endif